package se.strand.jpademo;

import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.PostLoad;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

@Entity
@Table(name = "person")
@NamedQuery(name = Person.QUERY_FIND_BY_NAME, query = Person.QUERY_FIND_BY_NAME_QUERY)
public class Person {
	public static final String SUBVERSION_ID = "$Id: Person.java 12 2007-04-19 12:31:50Z christer.wendel $";

	public static final String QUERY_FIND_BY_NAME = "find_by_name";

	public static final String QUERY_PARAMETER_NAME = "name";
	
	public static final String QUERY_FIND_BY_NAME_QUERY = "select person from Person as person where name = :" + Person.QUERY_PARAMETER_NAME; 

	@Id
	private int id;

	@Basic
	private String name;

	@Basic
	private boolean female;

	@Temporal(TemporalType.DATE)
	private Date birthDate;

	@Transient
	private int age;

	@ManyToOne
	private Person mother;

	@ManyToOne
	private Person father;

	@OneToMany(mappedBy = "father")
	private Set<Person> childrenWithFathers;

	@OneToMany(mappedBy = "mother")
	private Set<Person> childrenWithMothers; 

	@ManyToMany
	@JoinTable(name="friends", joinColumns = @JoinColumn(name = "person"), inverseJoinColumns = @JoinColumn(name="friend"))
	private Set<Person> friends;

	public int getAge() {
		return age;
	}

	public void setFemale(boolean female) {
		this.female = female;
	}

	public boolean isFemale() {
		return female;
	}

	@PostLoad
	public void setAge() {
		Calendar present = Calendar.getInstance();
		int presentYear = present.get(Calendar.YEAR);

		Calendar past = Calendar.getInstance();
		past.setTime(birthDate);
		int pastYear = past.get(Calendar.YEAR);

		present.set(Calendar.YEAR, pastYear);
		boolean hadBirthday = present.after(past);

		age = presentYear - pastYear;

		if (!hadBirthday) {
			age--;
		}
	}

	public Date getBirthDate() {
		return birthDate;
	}

	public void setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
	}

	public Person getMother() {
		return mother;
	}

	public void setMother(Person mother) {
		this.mother = mother;
	}

	public Person getFather() {
		return father;
	}

	public void setFather(Person father) {
		this.father = father;
	}

	public Set<Person> getChildren() {
		if (female) {
			if (childrenWithMothers == null) {
				childrenWithMothers = new HashSet<Person>();
			}

			return childrenWithMothers;
		} else {
			if (childrenWithFathers == null) {
				childrenWithFathers = new HashSet<Person>();
			}

			return childrenWithFathers;
		}
	}

	public void addFriend(Person friend) {
		if (friends == null) {
			friends = new HashSet<Person>();
		}

		friends.add(friend);

		if (friend.friends == null) {
			friend.friends = new HashSet<Person>();
		}

		friend.friends.add(this);
	}

	public void removeFriend(Person friend) {
		if (friends != null && friends.contains(friend)) {
			friends.remove(friend);
		}

		if (friend.friends != null && friend.friends.contains(this)) {
			friend.friends.remove(this);
		}
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set<Person> getFriends() {
		if (friends == null) {
			friends = new HashSet<Person>();
		}

		return friends;
	}
}
